package com.g13.virtualpethospital.service.Implement;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.g13.virtualpethospital.config.AssistantConfig;
import com.g13.virtualpethospital.controller.response.ErnieBotTurboResponse;
import com.g13.virtualpethospital.dto.AssistantSessionData;
import com.g13.virtualpethospital.entity.base.ChatMessage;
import com.g13.virtualpethospital.entity.base.ErnieBotTurboParam;
import com.g13.virtualpethospital.exceptions.ErnieBotException;
import com.g13.virtualpethospital.service.ErnieBotService;
import com.mongodb.client.result.DeleteResult;
import okhttp3.*;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @Title: ErnieBotServiceImpl
 * @Author yyj1205
 * @Package com.g13.virtualpethospital.service.Implement
 * @Date 15/4/2024 21:44
 * @description: ErineBotService的实现类
 */
@Service
public class ErnieBotServiceImpl implements ErnieBotService {
    @Autowired
    MongoTemplate mongoTemplate;
    @Autowired
    AssistantConfig assistantConfig;
    static final OkHttpClient okHttpClient = new OkHttpClient().newBuilder().build();
    @Override
    public String getSession() {
        AssistantSessionData sessionData = new AssistantSessionData(null, LocalTime.now(), new ArrayList<ChatMessage>());
        AssistantSessionData sessionDataNew = mongoTemplate.insert(sessionData);
        return sessionDataNew.getId();
    }

    @Override
    public void deleteSession(String sessionId) throws ErnieBotException {
        AssistantSessionData sessionData = mongoTemplate.findById(sessionId, AssistantSessionData.class);
        if(sessionData == null) throw new ErnieBotException(ErnieBotException.ErnieBotErrorCode.FIND_NO_SESSION);
        DeleteResult result = mongoTemplate.remove(new Query(Criteria.where("_id").is(sessionId)), AssistantSessionData.class);
        if(result.getDeletedCount() == 0) throw new ErnieBotException(ErnieBotException.ErnieBotErrorCode.DEL_FAIL);
    }

    @Override
    public String postMessage(String session_Id, String msg) throws ErnieBotException, IOException {
        if(msg == null) throw new ErnieBotException(ErnieBotException.ErnieBotErrorCode.NO_MSG);
        AssistantSessionData assistantSessionData = mongoTemplate.findById(session_Id, AssistantSessionData.class);
        if(assistantSessionData == null) throw new ErnieBotException(ErnieBotException.ErnieBotErrorCode.FIND_NO_SESSION);
        List<ChatMessage> messageList =  assistantSessionData.getMessageList();
        messageList.add(new ChatMessage("user", msg));
        ErnieBotTurboParam ernieBotTurboParam = new ErnieBotTurboParam(messageList,
                assistantConfig.getTemperature(),
                assistantConfig.getTop_p(),
                assistantConfig.getPenalty_score(),
                assistantConfig.getSystem(),
                assistantConfig.getMax_output_token(),
                assistantSessionData.getId());
        String postMsg = HttpUtil.post(assistantConfig.getInstanceuri() + "?access_token=" +
                        getAccessToken(assistantConfig.getAppKey(), assistantConfig.getSecretKey()),
                JSONUtil.toJsonStr(ernieBotTurboParam));
        ErnieBotTurboResponse response = JSONUtil.toBean(postMsg, ErnieBotTurboResponse.class);
        if(response.getNeed_clear_history()) {
            this.deleteSession(session_Id);
            throw new ErnieBotException(ErnieBotException.ErnieBotErrorCode.ILLEGAL_MSG);
        }
        messageList.add(new ChatMessage("assistant", response.getResult()));
        Update update = new Update();
        update.set("messageList", messageList);
        mongoTemplate.upsert(new Query(Criteria.where("_id").is(session_Id)),
                update,
                AssistantSessionData.class);
        return response.getResult();
    }
    String getAccessToken(String apiKey, String secretKey) throws IOException {
        MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
        RequestBody body = RequestBody.create(mediaType, "grant_type=client_credentials&client_id=" + apiKey
                + "&client_secret=" + secretKey);
        Request request = new Request.Builder()
                .url(assistantConfig.getTokenuri())
                .method("POST", body)
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .build();
        Response response = okHttpClient.newCall(request).execute();
        return new JSONObject(response.body().string()).getString("access_token");
    }
}
